﻿#region License

// PentaBiz - Sustainable Software Development Framework Copyright (C) 2013 Zoltán Csizmazia
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

#endregion

using System;

namespace PentaBiz.WpfTools.Threading
{
    /// <summary>
    ///     Static delegate extension class
    ///     <para>makes Delegate.Cast&lt;EventHandler&lt;TeventArg&gt;&gt; possible</para>
    /// </summary>
    internal static class ExtensionsDelegate
    {
        /// <summary>
        ///     Cast this delegate
        /// </summary>
        /// <typeparam name="T">Type of the result</typeparam>
        /// <param name="delegate"></param>
        /// <returns></returns>
        public static T Cast<T>(this Delegate @delegate) where T : class
        {
            return Cast(@delegate, typeof (T)) as T;
        }


        /// <summary>
        ///     Casts the specified @delegate.
        /// </summary>
        /// <param name="delegate">The @delegate.</param>
        /// <param name="targetType">Type of the target.</param>
        /// <returns></returns>
        public static Delegate Cast(Delegate @delegate, Type targetType)
        {
            if (@delegate == null)
                return null;


            Delegate[] delegates = @delegate.GetInvocationList();
            if (delegates.Length == 1)
                return Delegate.CreateDelegate(targetType,
                                               delegates[0].Target, delegates[0].Method);

            Delegate[] delegatesDest = new Delegate[delegates.Length];
            for (int nDelegate = 0; nDelegate < delegates.Length; nDelegate++)
                delegatesDest[nDelegate] = Delegate.CreateDelegate(targetType,
                                                                   delegates[nDelegate].Target,
                                                                   delegates[nDelegate].Method);

            //cobine delegate
            Delegate result = null;
            foreach (var d in delegatesDest)
            {
                if (result == null)
                    result = d;
                else
                {
                    result = Delegate.Combine(result, d);
                }
            }
            return result;
        }
    }
}